// Copyright (c) [2019] [huazhonghua]
// [理解] is licensed under the Mulan PSL v1.
// You can use this software according to the terms and conditions of the Mulan PSL v1.
// You may obtain a copy of Mulan PSL v1 at:
//     http://license.coscl.org.cn/MulanPSL
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
// PURPOSE.
// See the Mulan PSL v1 for more details.

#ifndef INITIALIZATION_H
#define INITIALIZATION_H

#include <wchar.h>

#include "structure.h"
#include "labels.h"
#include "execution.h"
#include "worker.h"
#include "operations.h"

void add_one_step_runner(Node* all, Node* node, int (*func)(ExecutionData* execution, Node* step)) {
	Node* ways = create_list_node(all, 1);
	link_node(node, WAY, ways);

	Node* way = create_node(all);
	add_to_list_node(ways, way);

	Node* steps = create_list_node(all, 1);
	link_node(way, STEP, steps);

	Node* step = create_node(all);
	add_to_list_node(steps, step);
	link_node(step, RUNNER, make_runner(all, func));
}

Node* build_execution(Node* all) {
	Node* language = get_linked(all, LANGUAGE);
	Node* chinese = find_by_c_string(all, all, L"中文", language);
	Node* english = find_by_c_string(all, all, L"English", language);

	Node* node = add_basic(all, OPERATION_RUNNER);
	node->other.pointer = run_operation;

	Node* binary_op = add_basic(all, BINARY_OPERATION);
	add_string_from_c(all, binary_op, L"binary operation", english);

	node = add_basic(all, ARRAY_ACCESS);
	add_string_from_c(all, node, L"[]", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 1));
	link_node(node, TYPE, binary_op);

	add_get_array_item_steps(all);
	add_get_create_array_item_steps(all);

	node = add_basic(all, ASSIGN);
	add_string_from_c(all, node, L"=", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 14));
	link_node(node, TYPE, binary_op);
	
	add_assign_link_steps(all);
	add_assign_variable_steps(all);
	add_assign_array_item_steps(all);

	node = add_basic(all, LINK_ACCESS);
	add_string_from_c(all, node, L".", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 1));
	link_node(node, TYPE, binary_op);

	add_get_linked_steps(all);
	add_get_create_linked_steps(all);

	node = add_basic(all, VARIABLE);
	add_string_from_c(all, node, L"variable", english);
	link_node(all, GET_VARIABLE, make_runner(all, get_variable));
	link_node(all, GET_CREATE_VARIABLE, make_runner(all, get_create_variable));

	node = add_basic(all, LESS);
	add_string_from_c(all, node, L"<", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 6));
	link_node(node, TYPE, binary_op);
	add_less_steps(all);

	node = add_basic(all, GREATER);
	add_string_from_c(all, node, L">", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 6));
	link_node(node, TYPE, binary_op);
	add_greater_steps(all);

	node = add_basic(all, LESS_EQUAL);
	add_string_from_c(all, node, L"<=", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 6));
	link_node(node, TYPE, binary_op);
	add_less_equal_steps(all);

	node = add_basic(all, GREATER_EQUAL);
	add_string_from_c(all, node, L">=", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 6));
	link_node(node, TYPE, binary_op);
	add_greater_equal_steps(all);

	node = add_basic(all, NOT_EQUAL);
	add_string_from_c(all, node, L"!=", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 7));
	link_node(node, TYPE, binary_op);
	add_not_equal_steps(all);

	node = add_basic(all, EQUAL);
	add_string_from_c(all, node, L"==", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 7));
	link_node(node, TYPE, binary_op);
	add_equal_steps(all);

	node = add_basic(all, AND);
	add_string_from_c(all, node, L"&&", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 11));
	link_node(node, TYPE, binary_op);
	add_and_steps(all);

	node = add_basic(all, OR);
	add_string_from_c(all, node, L"||", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 12));
	link_node(node, TYPE, binary_op);
	add_or_steps(all);

	node = add_basic(all, MINUS);
	add_string_from_c(all, node, L"-", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 4));
	link_node(node, TYPE, binary_op);
	add_minus_steps(all);

	node = add_basic(all, PLUS);
	add_string_from_c(all, node, L"+", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 4));
	link_node(node, TYPE, binary_op);
	add_plus_steps(all);

	node = add_basic(all, MULTIPLY);
	add_string_from_c(all, node, L"*", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 3));
	link_node(node, TYPE, binary_op);
	add_multiply_steps(all);

	node = add_basic(all, DIVIDE);
	add_string_from_c(all, node, L"/", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 3));
	link_node(node, TYPE, binary_op);
	add_divide_steps(all);

	node = add_basic(all, MODULO);
	add_string_from_c(all, node, L"%", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 3));
	link_node(node, TYPE, binary_op);
	add_mod_steps(all);

	node = add_basic(all, UNORDERED);
	add_string_from_c(all, node, L"无循序", chinese);
	add_string_from_c(all, node, L"unordered", english);
	link_node(node, PRECEDENCE, get_create_int(all, 2));

	node = create_node(all);
	node->other.pointer = run_unordered;
	link_node(all, UNORDERED_RUNNER, node);

	node = add_basic(all, RETURN);
	add_string_from_c(all, node, L"返回", chinese);
	add_string_from_c(all, node, L"return", english);
	link_node(node, PRECEDENCE, get_create_int(all, 16));
	add_return_steps(all);

	node = add_basic(all, NEGATION);
	add_string_from_c(all, node, L"-", NULL);
	link_node(node, PRECEDENCE, get_create_int(all, 2));

	node = add_basic(all, IF);
	add_string_from_c(all, node, L"如果", chinese);
	add_string_from_c(all, node, L"if", english);
	link_node(node, PRECEDENCE, get_create_int(all, 2));
	add_if_steps(all);

	node = add_basic(all, ADD_WAY);
	add_string_from_c(all, node, L"加算法", chinese);
	add_string_from_c(all, node, L"add way", english);
	link_node(node, PRECEDENCE, get_create_int(all, 2));
	add_add_way_steps(all);

	node = add_basic(all, GOAL_EXPRESSION);
	add_string_from_c(all, node, L"goal expression", english);
	add_goal_expression_steps(all);

	link_node(all, STEP_RUNNER, make_runner(all, run_steps));
}

Node* build_basic() {
	create_node = create_node_no_track;

	Node* all = create_node_only();

/*	Node* node_list = create_node_only();
	link_node(all, NODE_LIST, node_list);
	node_list->other.pointer = create_list(8);
	create_lock(all, node_list);*/

	Node* integer = add_basic(all, INTEGER);
	get_create_int(all, 0);
	get_create_int(all, 1);

	Node* list = add_basic(all, LIST);

//	link_node(node_list, TYPE, list);

	add_basic(all, INSTANCE);
	Node* c_char = add_basic(all, WCHAR_T);
	Node* string = add_basic(all, STRING);

	Node* language = add_basic(all, LANGUAGE);
	Node* chinese = create_instance(all, language);
	add_string_from_c(all, chinese, L"中文", chinese);
	Node* english = create_instance(all, language);
	add_string_from_c(all, english, L"English", english);

	Node* str_var = get_create_string(all, L"all", english);
	represent_by_string(all, all, str_var);
	add_string_from_c(all, integer, L"integer", english);
	add_string_from_c(all, list, L"list", english);
//	add_string_from_c(all, node_list, L"node list");
	add_string_from_c(all, string, L"字串", chinese);
	add_string_from_c(all, string, L"string", english);
	add_string_from_c(all, c_char, L"c wide character", english);

	Node* node = add_basic(all, WAY);
	add_string_from_c(all, node, L"way", english);

	node = add_basic(all, STEP);
	add_string_from_c(all, node, L"step", english);

	node = add_basic(all, TYPE);
	add_string_from_c(all, node, L"type", english);

	Node* goal = add_basic(all, GOAL);
	add_string_from_c(all, goal, L"目标", chinese);
	add_string_from_c(all, goal, L"goal", english);

	node = add_basic(all, PARAMETER);
	add_string_from_c(all, node, L"参数", chinese);
	add_string_from_c(all, node, L"parameter", english);

	node = add_basic(all, ARGUMENT);
	add_string_from_c(all, node, L"argument", english);

	node = create_instance(all, goal);
	add_string_from_c(all, node, L"建立", english);
	add_string_from_c(all, node, L"create", chinese);

	add_one_step_runner(all, node, run_create);

	node = add_basic(all, INSTANCE);
	add_string_from_c(all, node, L"instance", english);

	build_execution(all);

	return all;
}

#endif
